<?php
/*
单例类
支持单主多从数据库
*/

class sql
{
	protected $conn=null;
	protected $port=null;
	protected $host=null;
	protected $user=null;
	protected $pwd=null;
	protected $dbnum=null;
	protected $dbname=null;
	protected $_adjustCount=null;

	protected static $ins=null;

	protected function __construct(){}
	public static function getIns()
	{
		if(self::$ins)
		{
			return self::$ins;
		}
		self::$ins=new self();
		$cfg=cfg::getIns();

		if(!$cfg)
		{
			die('Please edit right conf.php');
		}
		//多数据库查询次数记录
		self::$ins->_adjustCount=0;
		$db=$cfg->db;
		//统计数据库个数
		self::$ins->dbnum=count($db);
		self::$ins->conn=array();
		self::$ins->host=array();
		self::$ins->user=array();
		self::$ins->pwd=array();
		self::$ins->port=array();
		self::$ins->dbname=array();
		
		self::$ins->charset=$cfg->charset;

		for($i=0;$i<self::$ins->dbnum;$i++)
		{
			/*foreach($db[$i] as $k=>$v)
			{
				$key=$k[$i];
				self::$ins->$key=$v;
				
			}
			*/
			$dn=$db[$i];
			self::$ins->host[$i]=$dn['host'];
			self::$ins->user[$i]=$dn['user'];
			self::$ins->pwd[$i]=$dn['pwd'];
			self::$ins->port[$i]=$dn['port'];
			self::$ins->dbname[$i]=$dn['dbname'];
			
			//self::$ins->conn[$i]='';

			//批量获取多个数据连接，加入到conn数组内
			//if(!self::$ins->conn[$i]=mysql_connect(self::$ins->host[$i],self::$ins->user[$i],self::$ins->pwd[$i],self::$ins->port[$i]))
			if(!self::$ins->conn[$i]=new PDO("mysql:host=".self::$ins->host[$i].';.dbname='.self::$ins->dbname[$i],self::$ins->user[$i],self::$ins->pwd[$i]))
			{
				//$e=new Exception("连接数据库出错".$i,1);
				//throw $e;
				//var_dump(self::$ins->conn[$i]);
				die('not connect');
			}
		}
		self::$ins->setChar();
		self::$ins->selectDB();
		return self::$ins;
	}

	public function __get($k)
	{
		if(isset($this->$k))
		{
			return $this->$k;
		}
		return false;
	}
	public function __set($k,$v){
		$this->$k=$v;
	}

	/*protected static function getCon($conn,$host,$user,$pwd,$port)
	{
		if(!$conn=mysql_connect($host,$user,$pwd,$port))
		{
			echo 'getCon';
			//$e=new Exception('连接数据库出错',1);
			//throw $e;
			//echo '连接数据库出错';
			return false;
		}
	}
	*/
	//选择使用字符串方法
	protected function setChar()
	{
		for($i=0;$i<$this->dbnum;$i++)
		{
			if(!$this->conn[$i]->query('SET NAMES '.$this->charset))
			//if(!mysql_set_charset($this->charset,$this->conn[$i]))
			{
				echo "set DB charset error in DB[$i]<br/>";
			}
		}
	}
	//内部选择数据库方法
	protected function selectDB()
	{
		for($i=0;$i<$this->dbnum;$i++)
		{
			if(!$this->conn[$i]->query('USE '.$this->dbname[$i]))
			//if(!mysql_select_db($this->dbname[$i],$this->conn[$i]))
			{
				echo "select DB error in DB[$i]<br/>";
			}
		}
		
	}
	
	protected function _adjust()
	{
		$_num=$this->dbnum;
		if($_num==1)
		{
			$where=0;
		}
		else if($_num==2)
		{
			$where=1;
		}
		else
		{
			$this->_adjustCount+=1;
			//存在多个数据库的话轮流读取
			$where=$this->_adjustCount%$_num;

			if($this->_adjustCount>$_num*100)
			{
				$this->_adjustCount=1;
			}
			
			
		}
		return $where;

	}

	public function lock($tb)
	{
		$i=$this->_adjust();
		$this->conn[$i]->query("LOCK TABLES '$tb' WRITE ");
		//mysql_query("LOCK TABLES '$tb' WRITE",$this->conn[$i]);
	}
	public function unlock()
	{
		$i=$this->_adjust();
		$this->conn[$i]->query("UNLOCK TABLES");
		//mysql_query("UNLOCK TABLES ",$this->conn[$i]);
	}


	public function get_query($sql)
	{
		$i=$this->_adjust();
		$res=$this->conn[$i]->query($sql);
		//$res=mysql_query($sql,$this->conn[$i]);
		
		if(!$res)
		{
			/*$e=new Exception("查询数据库$i出错:".$sql,'2');
			throw $e;
			*/
			//echo '查询数据库出错'.$sql;
			return false;
		}
		return $res;
	}
	
	public function set_query($sql)
	{
		$res=$this->conn[0]->query($sql);
		//$res=mysql_query($sql,$this->conn[0]);
		if(!$res)
		{
			echo '插入或更新出错'.$sql;
			/*$e=new Exception('插入或更新出错:'.$sql,'2');
			throw $e;
			*/
			return false;
		}
		return $res;
	}

	public function getAll($sql)
	{
		$rs=$this->get_query($sql);
		if(!$rs)
		{
			return false;
		}
		$list=array();
		while($row=$rs->fetch())
		{
			$list[]=$row;
		}
		/*
		while($row=mysql_fetch_assoc($rs))
		{
			$list[]=$row;
		}
		*/
		return $list;
	}
	public function getRow($sql)
	{
		$rs=$this->get_query($sql);
		if(!$rs)
		{
			return false;
		}
		//return mysql_fetch_assoc($rs);
		return $rs->fetch(PDO::FETCH_ASSOC);
	}
	
	public function getOne($sql)
	{
		$rs=$this->get_query($sql);
		if(!$rs)
		{
			return false;
		}
		//$one=mysql_fetch_row($rs);
		$one=$rs->fetch();
		return $one[0];
	}
	
	public function affect_row()
	{
		return 1;
		//return mysql_affected_rows($this->conn[0]);
		//return $this->conn[0]->rowCount();
	}
	
	public function insert_id()
	{
		//return mysql_insert_id($this->conn[0]);
		return $this->conn[0]->lastInsertId();
	}
	
	public function insert($table,$data)
	{
		$sql='insert into '.$table.' (';
		$sql.=implode(',', array_keys($data)).') values ("';
		$sql.=implode('","', array_values($data)).'")';

		return $this->set_query($sql);
	}
	public function update($table,$data,$id)
	{
		$sql='update '.$table.' set ';
		
		foreach ($data as $k=>$v)
		{
			$sql.=$k.'="'.$v.'",';
		}
		$sql=substr($sql, 0,-1);
		$sql.=' where id = "'.$id.'"';
		return $this->set_query($sql);
	}

	public function updatebyattr($table,$data,$attr,$attrval)
	{
		$sql='update '.$table.' set ';
		foreach ($data as $k=>$v)
		{
			$sql.=$k.'="'.$v.'",';
		}
		$sql=substr($sql, 0,-1);
		$sql.=' where '.$attr.' = "'.$attrval.'"';
		return $this->set_query($sql);
	}
	public function delete($att,$table)
	{
		$sql="delete from {$table} where {$att}";
		return $this->set_query($sql);
	}
}